Реализуйте шаблонный класс Polynomial («Многочлен от одной переменной»). Тип коэффициентов многочлена передавайте в качестве параметра шаблона. Хранение коэффициентов должно быть плотным (то есть, должны храниться все коэффициенты, в том числе и промежуточные нулевые). Предусматривать возможность работы с нецелыми или отрицательными степенями не нужно.

Сделайте следующее:

* Напишите конструктор по умолчанию, создающий нулевой многочлен
* Напишите конструктор, создающий многочлен нулевой степени по указанному коэффициенту.
* Напишите конструктор, принимающий `std::initializer_list` коэффициентов
* Определите операторы == и !=. Ваш код должен быть очень простым.
* Определите операторы +, -, *, а также соответствующие операторы вида @=. Учтите, что должны быть определены и такие арифметические операции, в которых один из аргументов является скаляром.
* Определите операторы / и /= для случая деления полинома на скаляр.
* Напишите функцию Degree для вычисления степени многочлена (считайте, что у нулевого многочлена степень равна -1).
* Определите операторы [ ] для получения или изменения коэффициента многочлена перед заданной степенью переменной. Оператор должен работать для любых степеней (в том числе, больших текущей максимальной).
* Определите оператор () для вычисления значения многочлена в точке. Постарайтесь написать эффективный код.
* Определите оператор << для печати многочлена в поток вывода.
* Определите функции begin и end для доступа к итераторам (в том числе, константного и реверсивного доступа), позволяющим перебирать или изменять коэффициенты многочлена.
* Увеличение степени многочлена может инвалидировать итераторы и ссылки.
* Уменьшение степени многочлена не должно инвалидировать ссылки.
* Оператор << должен выводить полином в человекочитаемом виде (`-x + 2*x^2 + x^10`)

В качестве заготовки cmake-проекта воспользуйтесь материалами курса:
https://github.com/ivafanas/cpp_shad_students/tree/master/2021/sem1/lab2_stub

Продемонстрируйте работу с объектами созданного класса на примерах. Подразумевается, что экземпляр класса будет создаваться так:

```c++
#include "polynomial.h"

int main (int argc, char∗ argv [ ]) {
  Polynomial<float> a ( . . . );
  Polynomial<float> b ( . . . );
  Polynomial<float> c = a * b;
  c ∗= 2.f;

  ...
}
```

Примеры, которые должны работать корректно (для направления мысли):

* Пример 1:

``` c++
Polynom<double> a(3);
a[5] = 42.0;
std::cout << a[5]; // must be 42
```

* Пример 2:

``` c++
Polynom<int> a;
const Polynom<int>& b = a;
a[5] = 42;
std::cout << b[5]; // must be 42
```

* Пример 3:

``` c++
Polynom<int> a;
a[1] = 1;
a[3] = 3;
a[5] = 5;
a[5] = 0;
std::cout << a.degree(); // must be 3
```

* Пример 4:

``` c++
Polynom<int> a;
a[0] = 3;
a[1] = 5;
const Polynom<int> b = a;
for (auto it = b.begin(); it != b.end(); ++it)
    std::cout << *it << std::endl;
```

* Пример 5:

``` c++
Polynom<double> a(3);
const auto& b = a;
const double& c5 = b[5];
a[4] = 7.0;
a[5] = 42.0;
std::cout << c5; // must print "42.0"
```

* Пример 6:

```c++
Polynomial<int> p({1, 2, 3, 4});
int& tmp = p[3];
p *= 0;
tmp = 10;
```

* Пример 7:

```c++
Polynomial<int> p1({1, 2, 3, 4});
Polynomial<int> p2({5, 6});
int& tmp = p1[3];
p1 = p2;
tmp = 10;
```

* Пример 8:

```c++
Polynomial<float> p1({1, 2, 3, 4});
float& coef = p1[3];
p1[3] = 0.f;
std::cout << coef; // код должен быть валиден и вернуть 0.f
```

Прочие замечания:

* Ознакомьтесь с ключевым словом `mutable`
* Посмотрите на интерфейс std::vector и его итераторов
* Формализованные требования к random access iterator:
http://www.cplusplus.com/reference/iterator/RandomAccessIterator/

